package com.wanxi.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.wanxi.dao.ESNewsDao;
import com.wanxi.dao.NewsDao;
import com.wanxi.dto.ResultDTO;
import com.wanxi.model.News;
import com.wanxi.service.NewsService;
import com.wanxi.util.CreateOnlyID;
import com.wanxi.util.DelHtmlTag;
import com.wanxi.util.JsonCopy;
import com.wanxi.vo.NewsVO;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class NewsServiceImpl implements NewsService {
    @Autowired
    NewsDao newsDao;

    @Autowired
    ESNewsDao esNewsDao;
    @Autowired
    CreateOnlyID createOnlyId;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;


    @Override
    public ResultDTO findAllNews() {
        List<News> list = newsDao.findAllNews();
        if (list.size() > 0) {
//            删除html标签
            list.forEach((e) -> {
                e.setContent(DelHtmlTag.delHtmlTags(e.getContent()));
            });
//            清空后装填到es
//            esNewsDao.saveAll(list);

            return ResultDTO.getDTO(list.size(), list);
        }
        return ResultDTO.builder().data(list).msg("no data").count(0).code(1).build();
    }

    @Override
    public ResultDTO findNewsById(NewsVO newsVO) {
        News news = JsonCopy.copy(newsVO, News.class);
        News n = newsDao.findNewsById(news);
        if (n != null) {
            return ResultDTO.getDTO(1, n);
        }
        return ResultDTO.builder().count(0).msg("error").code(1).build();
    }

    @Override
    public ResultDTO updateEnable(NewsVO newsVO) {
        News news = JsonCopy.copy(newsVO, News.class);
        int i = newsDao.updateById(news);
        if (i == 1) {
            Long id = ((News) findNewsById(newsVO).getData()).getNewsType().getId();
            stringRedisTemplate.delete("newsType:" + id);
            return ResultDTO.getDTO(i, newsVO);
        }
        return ResultDTO.builder().data(newsVO).count(0).code(1).msg("error").build();
    }

    @Override
    public ResultDTO addNews(NewsVO newsVO) {
        News news = JsonCopy.copy(newsVO, News.class);
        Long newsTypeId = news.getNewsType().getId();
        if (newsTypeId != null && newsTypeId == 0L) {
            news.getNewsType().setId(1L);
        }
        news.setId(createOnlyId.createId());
        newsVO.setId(news.getId());
        int i = newsDao.addNews(news);
        if (i == 1) {
            Long id = ((News) findNewsById(newsVO).getData()).getNewsType().getId();
            stringRedisTemplate.delete("newsType:" + id);
            return ResultDTO.getDTO(i, newsVO);
        }
        return ResultDTO.builder().data(newsVO).count(0).code(1).msg("error").build();
    }

    @Override
    public ResultDTO deleteNews(NewsVO newsVO) {
        News news = JsonCopy.copy(newsVO, News.class);
        int i = newsDao.deleteById(news);
        if (i == 1) {
            Long id = newsVO.getId();
            stringRedisTemplate.delete("newsType:" + id);
            return ResultDTO.getDTO(i, newsVO);
        }
        return ResultDTO.builder().data(newsVO).count(0).code(1).msg("error").build();
    }

    @Override
    public ResultDTO updateNews(NewsVO newsVO) {
        News news = JsonCopy.copy(newsVO, News.class);
        Long newsTypeId = news.getNewsType().getId();
        if (newsTypeId != null && newsTypeId == 0L) {
            news.getNewsType().setId(1L);
        }
        int i = newsDao.updateNews(news);
        if (i == 1) {
            Long id = ((News) findNewsById(newsVO).getData()).getNewsType().getId();
            stringRedisTemplate.delete("newsType:" + id);
            return ResultDTO.getDTO(i, newsVO);
        }
        return ResultDTO.builder().data(newsVO).count(0).code(1).msg("error").build();
    }

    @Override
    public ResultDTO findNews(NewsVO newsVO) {
        News news = JsonCopy.copy(newsVO, News.class);
        Long len = stringRedisTemplate.opsForList().size("newsType:" + newsVO.getNewsType().getId());
//        判断redis中是否有数据
        if (len != 0) {
//            返回redis中的数据,通过fastJson转换
            List<String> redisNews = stringRedisTemplate.opsForList()
                    .range("newsType:" + newsVO.getNewsType().getId(), 0, len);
            List<News> list = JSON.parseObject(redisNews.toString(), new TypeReference<List<News>>() {
            });
//            删除html标签、限长度
            list.forEach((e) -> {
                e.setContent(DelHtmlTag.delHtmlTags(e.getContent()));
                int maxLength = 15;
                if (e.getContent().length() > maxLength) {
                    e.setContent(e.getContent().substring(0, 14) + "...");
                }
            });
            return ResultDTO.getDTO(list.size(), list);
        }
//        没有则从数据库中找数据
        List<News> list = newsDao.findNews(news);
        if (list.size() > 0) {
//            Dao层数据迭代
            Iterator<News> iterator = list.iterator();
            while (iterator.hasNext()) {
                News n = iterator.next();
                if (n.getEnable() == 0) {
                    iterator.remove();
                } else {
//                    将查到的数据放入redis
                    stringRedisTemplate.expire("newsType:" + newsVO.getNewsType().getId(), 300, TimeUnit.SECONDS);
                    stringRedisTemplate.opsForList().rightPush("newsType:" + newsVO.getNewsType().getId(), JSON.toJSONString(n));
                }
            }
//            删除html标签、限长度
            list.forEach((e) -> {
                e.setContent(DelHtmlTag.delHtmlTags(e.getContent()));
                int maxLength = 15;
                if (e.getContent().length() > maxLength) {
                    e.setContent(e.getContent().substring(0, 14) + "...");
                }
            });
            return ResultDTO.getDTO(list.size(), list);
        }
        return ResultDTO.builder().data(list).msg("no data").count(0).code(1).build();
    }

    @Override
    public ResultDTO findNewsBySome(NewsVO newsVO) {
        News news = JsonCopy.copy(newsVO, News.class);
        Set<News> set = new HashSet<>();
        //模糊值不能都为空
        if (news.getTitle() != null || news.getContent() != null) {
            if (news.getTitle() == null) {
                List<News> newsByContent = esNewsDao.findNewsByContent(news.getContent());
                //高亮处理
                newsByContent.forEach(e -> {
                    e.setContent(
                            e.getContent().replaceAll(news.getContent(),
                                    "<font color='red'>" + news.getContent() + "</font>")
                    );
                });
                set.addAll(newsByContent);
            } else if (news.getContent() == null) {
                List<News> newsByTitle = esNewsDao.findNewsByTitle(news.getTitle());
                //高亮处理
                newsByTitle.forEach(e -> {
                    e.setTitle(
                            e.getTitle().replaceAll(news.getTitle(),
                                    "<font color='red'>" + news.getTitle() + "</font>")
                    );
                });
                set.addAll(newsByTitle);
            } else {
                set.addAll(esNewsDao.findNewsByTitleAndContent(news.getTitle(), news.getContent()));
                //高亮处理
                set.forEach(e -> {
                    e.setTitle(e.getTitle().replaceAll(news.getTitle(), "<font color='red'>" + news.getTitle() + "</font>"));
                    e.setContent(e.getContent().replaceAll(news.getContent(), "<font color='red'>" + news.getContent() + "</font>"));
                });
            }
        }
//        List<News> list =newsDao.findNewsBySome(news);
        if (set.size() > 0) {
//            删除html标签
//            list.forEach((e)->{
//                e.setContent(DelHtmlTag.delHtmlTags(e.getContent()));
//            });
            return ResultDTO.getDTO(set.size(), set);
        }
        return ResultDTO.builder().data(set).msg("no data").count(0).code(1).build();
    }

    @Scheduled(cron = "0/50 * * * * ? ")
    public void saveInES() {
        List<News> allNews = newsDao.findAllNews();
//            删除html标签
        allNews.forEach((e) -> {
            e.setContent(DelHtmlTag.delHtmlTags(e.getContent()));
        });
//            清空后装填到es
            esNewsDao.saveAll(allNews);
    }
}
